﻿// <copyright file="GeoRSSDal.cs" company="The MITRE Corporation">
//    Copyright (c) 2010 The MITRE Corporation. All rights reserved.
// </copyright>
// ———————————————————————–
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-09-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)        
/////////////////////////////////////////////////////////////////////////////////////////////////
// GeoRSSDal.cs - Data Access Layer to Add Geo-RSS Items
// Project: IC.NET SOA - IC.NET DAL
//
// Language:    C#, .NET 4.0
// Platform:    Dell XPS m1530 Windows 7, VS 2010 Beta 2
// Author:      Don McGarry MITRE Rome
/////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2010 The MITRE Corporation. All rights reserved.
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-09-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml.Linq;
using EDXLSharp;
using EDXLSharp.EDXLDELib;
using ICNETServices;

namespace ICNETDAL
{
  /// <summary>
  /// A collection of methods for adding Geo-RSS items to the ICNET database
  /// </summary>
  public static class GeoRSSDal
  {
    #region Public Delegates/Events

    #endregion

    #region Private Member Variables

    #endregion

    #region Public Accessors

    #endregion

    #region Constructors

    #endregion

    #region Public Member Functions

    /// <summary>
    /// Deletes entries in the exposure cache that are over 12 hours old.
    /// </summary>
    public static void DeleteStaleExposureCacheEntries()
    {
      //make sure the duration is negative, so the where clause below works correctly
      //we want to delete everything older than the duration ago
      double duration = (System.Math.Abs(ICNETSOAConstants.CacheClearDurationInMinutes) * -1.0);

      EDXLSQLDataContext db = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);

      var emergencyMessageContinerIDs = (
        from ec in db.ExposureCaches
        join emContent in db.EmergencyMessageContents on ec.EmergencyMessageContentId equals emContent.Id
        join emContainer in db.EmergencyMessageContainers on emContent.EmergencyMessageContainerId equals emContainer.Id
        where ec.PublishDate <= DateTime.UtcNow.AddMinutes(duration)
        select emContainer.Id).Distinct();

      EmergencyMessageContainer emergencyMessageContainer;
      foreach (var id in emergencyMessageContinerIDs)
      {
        emergencyMessageContainer =
          db.EmergencyMessageContainers.SingleOrDefault(
            emc => emc.Id == id);
        if (emergencyMessageContainer != null)
        {
          db.EmergencyMessageContainers.DeleteOnSubmit(emergencyMessageContainer);
        }
      }

      db.SubmitChanges();
    }

    /// <summary>
    /// Make a GEORSS feed from an XML content object
    /// </summary>
    /// <param name="co">The content object to be syndicated.</param>
    /// <returns>A list, where each object in the list is a Syndication item on the feed.</returns>
    public static List<SyndicationItem> GetXMLContentSyndicationItems(ContentObject co)
    {
      List<IGeoRSS> geoRSSItems = new List<IGeoRSS>();
      DEDalUtils.UnboxContentObjectForGeoRSS(co, geoRSSItems);
      List<SyndicationItem> synItems = new List<SyndicationItem>();
      Guid contentKey = new Guid();
      foreach (IGeoRSS item in geoRSSItems)
      {
        item.ToGeoRSS(synItems, contentKey);
      }
      ////foreach (SyndicationItem Sitem in synItems)
      ////{
      ////  SynItemToGeoRSSDB(Sitem, contentKey, Co.ConsumerRole);
      ////}
      return synItems;
    }

    /// <summary>
    /// Creates a GeoRSS feed from a nonXML content object
    /// </summary>
    /// <param name="co">The content object to be syndicated.</param>
    /// <returns>A list, where each object in the list is a Syndication item on the feed.</returns>
    public static List<SyndicationItem> GetNonXMLContentSyndicationItems(ContentObject co)
    {
      List<SyndicationItem> synItems = new List<SyndicationItem>();
      Guid contentKey = new Guid();
      co.NonXMLContent.ToGeoRSS(synItems, contentKey);
      return synItems;
    }

    /// <summary>
    /// Gets all of the objects from the exposure cache, orders them by date, and then turns them into a GeoRSS feed
    /// </summary>
    /// <returns>A list, where each item in the list is an item on the GeoRSS feed.</returns>
    public static List<SyndicationItem> GetAllGeoRSS()
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }

    /// Gets all of the objects from the exposure cache, orders them by date, and then turns them into a GeoRSS feed
    /// </summary>
    /// <returns>A list, where each item in the list is an item on the GeoRSS feed.</returns>
    public static List<SyndicationItem> GetActiveGeoRSS()
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      where p.ExpirationTime > DateTime.UtcNow
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }

    /// Gets all of the objects from the exposure cache, orders them by date, and then turns them into a GeoRSS feed
    /// </summary>
    /// <returns>A list, where each item in the list is an item on the GeoRSS feed.</returns>
    public static List<SyndicationItem> GetExpiredGeoRSS()
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      where p.ExpirationTime <= DateTime.UtcNow
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }

    /// Gets all of the objects from the exposure cache, orders them by date, and then turns them into a GeoRSS feed
    /// </summary>
    /// <returns>A list, where each item in the list is an item on the GeoRSS feed.</returns>
    public static List<SyndicationItem> GetUpdatedGeoRSS(DateTime Since)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      where p.LastUpdatedTime >= Since.ToUniversalTime()
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }

    /// <summary>
    /// Queries the Exposure Cache To Get The Items Which Match The Given Role
    /// </summary>
    /// <param name="role">Name of the Role To Join on</param>
    /// <param name="roleURI">The URI Indicating the Unique Name of the List That The Given
    /// role corresponds to</param>
    /// <returns>A List of Syndication Items</returns>
    public static List<SyndicationItem> GetSyndicationItemsByRole(string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in linqDB.ExposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }

    /// <summary>
    /// Queries the Exposure Cache To Get The Items Which Match The Given Role
    /// </summary>
    /// <param name="role">Name of the Role To Join on</param>
    /// <param name="roleURI">The URI Indicating the Unique Name of the List That The Given
    /// role corresponds to</param>
    /// <returns>A List of Syndication Items</returns>
    public static List<SyndicationItem> GetActiveSyndicationItemsByRole(string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);

      var exposureCaches = from p2 in linqDB.ExposureCaches
                           where p2.ExpirationTime > DateTime.UtcNow
                           select p2;

      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in exposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }

    /// <summary>
    /// Queries the Exposure Cache To Get The Items Which Match The Given Role
    /// </summary>
    /// <param name="role">Name of the Role To Join on</param>
    /// <param name="roleURI">The URI Indicating the Unique Name of the List That The Given
    /// role corresponds to</param>
    /// <returns>A List of Syndication Items</returns>
    public static List<SyndicationItem> GetExpiredSyndicationItemsByRole(string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);

      var exposureCaches = from p2 in linqDB.ExposureCaches
                           where p2.ExpirationTime <= DateTime.UtcNow
                           select p2;

      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in exposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }

    /// <summary>
    /// Queries the Exposure Cache To Get The Items Which Match The Given Role
    /// </summary>
    /// <param name="role">Name of the Role To Join on</param>
    /// <param name="roleURI">The URI Indicating the Unique Name of the List That The Given
    /// role corresponds to</param>
    /// <returns>A List of Syndication Items</returns>
    public static List<SyndicationItem> GetUpdatedSyndicationItemsByRole(DateTime Since, string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);

      var exposureCaches = from p2 in linqDB.ExposureCaches
                           where p2.LastUpdatedTime >= Since.ToUniversalTime()
                           select p2;

      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in exposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> expCacheList = headlines.ToList<ExposureCache>();

      return GetGeoRSS(expCacheList, linqDB);
    }
    #endregion

    #region Protected Member Functions

    #endregion

    #region Private Member Functions
    /// <summary>
    /// Gets all of the objects from the exposure cache, orders them by date, and then turns them into a GeoRSS feed
    /// </summary>
    /// <returns>A list, where each item in the list is an item on the GeoRSS feed.</returns>
    private static List<SyndicationItem> GetGeoRSS(IList<ExposureCache> ExposureCacheList, EDXLSQLDataContext linqDB)
    {
      List<SyndicationItem> myList = new List<SyndicationItem>();
      SyndicationItem myItem;

      foreach (ExposureCache databaseItems in ExposureCacheList)
      {
        myItem = new SyndicationItem();
        myItem.Authors.Add(new SyndicationPerson(databaseItems.Author));
        myItem.BaseUri = new Uri(databaseItems.BaseUri);
        myItem.Content = new TextSyndicationContent(databaseItems.Content);
        myItem.Copyright = new TextSyndicationContent(databaseItems.Copyright);
        SelectExposureWhereResult xevar;

        try
        {
          xevar = linqDB.SelectExposureWhere(databaseItems.Id).First();
          if (xevar == null)
          {
            continue;
          }
        }
        catch
        {
          continue;
        }

        XElement xe = xevar.Column1;
        if (databaseItems.Circle != string.Empty && databaseItems.Circle != null)
        {
          xe = DEDalUtils.CircletoGeoRSSSimple(databaseItems.Circle);
          myItem.ElementExtensions.Add(xe);
        }
        else if (xe != null)
        {
          xe = DEDalUtils.GmltoGeoRSSSimple(xe);
          myItem.ElementExtensions.Add(xe);
        }

        if (databaseItems.ContentHash.HasValue)
        {
          myItem.Id = databaseItems.ContentHash.Value.ToString();
        }
        else
        {
          myItem.Id = databaseItems.Id.ToString();
        }
        myItem.LastUpdatedTime = databaseItems.LastUpdatedTime;

        if (!databaseItems.Summary.Contains("NonXMLContent"))
        {
          myItem.Links.Add(new SyndicationLink(new Uri(databaseItems.Link))); ////HTML link is expected to be in database

          string xmlLink = databaseItems.Link.Replace("HTML", "XML");
          myItem.Links.Add(new SyndicationLink(new Uri(xmlLink), "alternate", "Download Link", "text/xml", 1000));
        }
        else
        {
          myItem.Links.Add(new SyndicationLink(new Uri(databaseItems.Link)));
        }

        myItem.PublishDate = databaseItems.PublishDate;
        myItem.Summary = new TextSyndicationContent(databaseItems.Summary);

        string title = databaseItems.Title;
        title = title.Replace("(Los Angeles)", string.Empty);
        title = title.Replace("(EDXL-HAVE)", string.Empty);
        title = title.Replace("(EDXL-CAP)", string.Empty);
        title = title.Replace("(CoT)", string.Empty);
        title = title.Replace("(EDXL-SitRep)", string.Empty);
        title = title.Replace("  ", " ").Trim();

        myItem.Title = new TextSyndicationContent(title);

        //add any extentions
        var ecExt = from o in linqDB.ExposureCacheExtensions
                    where o.ExposureCacheId == databaseItems.Id
                    select o;
        if (ecExt != null)
        {
          IList<ExposureCacheExtension> expCacheListExt = ecExt.ToList<ExposureCacheExtension>();

          foreach (ExposureCacheExtension ext in expCacheListExt)
          {
            myItem.ElementExtensions.Add(ext.Key, ICNETSOAConstants.ICNETNamespace, ext.Value);
          }
        }

        myList.Add(myItem);
      }

      return myList;
    }
    #endregion
  }
}
